package com.linshengjian.snowball.guard.filter;

import com.linshengjian.snowball.guard.GuardProperties;
import com.linshengjian.snowball.guard.UserLoginType;
import com.linshengjian.snowball.guard.service.GuardUserService;
import com.linshengjian.snowball.guard.utils.TokenUtils;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.bind.annotation.ModelAttribute;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 登录验证，各种登录方式在这里验证
 */
public class LoginAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

//    public final static String VerifyLoginName = "verify-login-name";

    private GuardProperties properties;
    private GuardUserService service;

    public LoginAuthenticationFilter(GuardProperties properties, GuardUserService service) {
        this.service = service;
        this.properties = properties;
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {

        String typeStr = request.getHeader(properties.getLogin().getHeader().getType());
        if (typeStr == null)
            typeStr = UserLoginType.Password.name();

        UserLoginType type = UserLoginType.valueOf(typeStr);

        if (UserLoginType.VerifyCode.equals(type)) {
            String verifyObj = (String) request.getSession().getAttribute(VerifyCodeFilter.VerifyObjectSession);
            UserDetails details = service.findByVerifyObj(verifyObj);
            if (details == null)
                return null;

            return new UsernamePasswordAuthenticationToken(details, details.getPassword(), details.getAuthorities());
        } else if (UserLoginType.ThirdParty.equals(type)) {
            UserDetails details = service.findByThirdParty(request);
            if (details == null)
                return null;
            return new UsernamePasswordAuthenticationToken(details, details.getPassword(), details.getAuthorities());
        } else {
            return super.attemptAuthentication(request, response);
        }
    }

    @Override
    @ModelAttribute
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {

        TokenUtils utils = new TokenUtils(properties);

        String token = utils.generate(((UserDetails) authResult.getPrincipal()).getUsername());

        response.addHeader(properties.getToken().getHeader(), properties.getToken().getTokenHead() + token);
        super.successfulAuthentication(request, response, chain, authResult);
    }
}
